#include "processing.h"
#include <QVector>
#include <QColor>
#include <QDebug>
#include <math.h>

inline QVector< char > RgbToYuv(const QRgb & rgb){
	QVector< char > res(3);
	res[0] = 0.299 * qRed(rgb) + 0.587 * qGreen(rgb) + 0.114 * qBlue(rgb);
	res[1] = -0.14713 * qRed(rgb) - 0.28886 * qGreen(rgb) + 0.436 * qBlue(rgb);
	res[2] = 0.615 * qRed(rgb) - 0.51499 * qGreen(rgb) - 0.10001 * qBlue(rgb);
}

inline QRgb YuvToRgb(const QVector< char > & YUV){
	QColor c;
	c.setRed(YUV[0] + 1.13983 * YUV[2]);
	c.setGreen(YUV[0] - 0.39465 * YUV[1] - 0.58060 * YUV[2]);
	c.setBlue(YUV[0] + 2.03211 * YUV[1]);
	return c.rgb();
}

inline QRgb sred(const QImage &img){
	QMap<QRgb, int> c;
	for(int i = 0; i < img.height(); ++i)
		for(int j = 0; j < img.width(); ++j){
			if(c.contains(img.pixel(i, j)))
				++c[img.pixel(i, j)];
			else
				c[img.pixel(i, j)] = 1;
		}
	return c.values().at(c.size()/2);
}

Processing::Processing(QObject *parent) :
    QObject(parent){}

/** Яркость.*/
void Processing::Brightness(QImage * img, double bright){
//	QVector< char > YUV(3);
	QColor c;
	QRgb rgb;
	if(bright < -1)
		bright = -1;
	if(bright > 1)
		bright = 1;
	if(bright > 0)
		for(int i = 0; i < img->height(); ++i)
			for(int j = 0; j < img->width(); ++j){
				rgb = img->pixel(j, i);
				c.setRed(round(qRed(rgb) + (255 - qRed(rgb)) * bright));
				c.setGreen(round(qGreen(rgb) + (255 - qGreen(rgb)) * bright));
				c.setBlue(round(qBlue(rgb) + (255 - qBlue(rgb)) * bright));
				img->setPixel(j, i, c.rgb());
		}
	else
		for(int i = 0; i < img->height(); ++i)
			for(int j = 0; j < img->width(); ++j){
			rgb = img->pixel(j, i);
			c.setRed(round(qRed(rgb) + qRed(rgb) * bright));
			c.setGreen(round(qGreen(rgb) + qGreen(rgb) * bright));
			c.setBlue(round(qBlue(rgb) + qBlue(rgb) * bright));
			img->setPixel(j, i, c.rgb());
		}
}

/** Бинаризация.*/
void Processing::Binary(QImage * img){
	QColor c;
	QRgb rgb;
	int sum;
	int n = 122 * 3;
	for(int i = 0; i < img->height(); ++i)
		for(int j = 0; j < img->width(); ++j){
			rgb = img->pixel(j, i);
			sum =  qRed(rgb);
			sum += qGreen(rgb);
			sum += qBlue(rgb);
			if(sum <= n) c.setRgb(0);
			if(sum > n) c.setRgb(255, 255, 255);
			img->setPixel(j, i, c.rgb());
		}
}

/** Яркостный срез.*/
void Processing::BrightCut(QImage * img, int n){
	QColor c;
	QRgb rgb;
	int r, g, b;
	for(int i = 0; i < img->height(); ++i)
		for(int j = 0; j < img->width(); ++j){
			rgb = img->pixel(j, i);
			r =  qRed(rgb);
			g = qGreen(rgb);
			b = qBlue(rgb);
			if(r > n) r = 255;
			if(g > n) g = 255;
			if(b > n) b = 255;
			c.setRed(r);
			c.setGreen(g);
			c.setBlue(b);
			img->setPixel(j, i, c.rgb());
		}
}

/** Инвертирование.*/
void Processing::Inverting(QImage * img, int n){
	QColor c;
	QRgb rgb;
	int r, g, b;
	for(int i = 0; i < img->height(); ++i)
		for(int j = 0; j < img->width(); ++j){
			rgb = img->pixel(j, i);
			r =  qRed(rgb);
			g = qGreen(rgb);
			b = qBlue(rgb);
			if(r < n)
				r = n - r;
			if(g < n)
				g = n - g;
			if(b < n)
				b = n - b;
			c.setRed(r);
			c.setGreen(g);
			c.setBlue(b);
			img->setPixel(j, i, c.rgb());
		}
}

/** Сглаживающий фильтр.*/
void Processing::Smoothing(QImage * img){
	Filter(img, QVector< QVector<double> >(3, QVector<double>(3, (double)1/9)));
}

/** Фильтр Гаусса.*/
void Processing::GaussFilter(QImage * img, double sigma){
	qDebug()<<1;
	QVector< QVector<double> > a;
	for(int i = 1; i <= 3; ++i){
		a.append(QVector<double>());
		for(int j = 1; j <= 3; ++j){
			a[i-1].append(1/(2*M_PI*sigma*sigma) * pow(M_E, -(j * j + i * i)/(2*sigma*sigma)));
		}
	}
	qDebug()<<2;
	Filter(img, a);
	qDebug()<<3;
}

/** Фильтр.*/
void Processing::Filter(QImage * img, QVector< QVector<double> > a){
	QColor c;
	QRgb rgb;
	double buffR, buffG, buffB;
	int m = a.at(0).size();
	int n = a.size();
	for(int i = m / 2; i < img->width() - m / 2; ++i)
		for(int j = n / 2; j < img->height() - n / 2; ++j){
		// Взяли очередной пиксель.

		buffR = 0;
		buffG = 0;
		buffB = 0;
		for(int k = 0; k < m; ++k )
			for(int l = 0; l < n; ++l ){
			buffR += a.at(l).at(k) * qRed(img->pixel(i - m / 2 + k, j - n / 2 + l));
			buffG += a.at(l).at(k) * qGreen(img->pixel(i - m / 2 + k, j - n / 2 + l));
			buffB += a.at(l).at(k) * qBlue(img->pixel(i - m / 2 + k, j - n / 2 + l));
			qDebug()<<buffR<<' '<<buffG<<' '<<buffB;
		}
		qDebug()<<' ';
		c.setRed(round(buffR));
		c.setGreen(round(buffG));
		c.setBlue(round(buffB));
		img->setPixel(i, j, c.rgb());
	}
}

void Processing::contrast(QImage * img, double k){
	QColor c;
	QRgb rgb;
	int r, g, b;
	k = (100 + k)/100;
	k *= k;
	for(int i = 0; i < img->height(); ++i)
		for(int j = 0; j < img->width(); ++j){
			rgb = img->pixel(j, i);
			r =  qRed(rgb);
			g = qGreen(rgb);
			b = qBlue(rgb);
			r = round(((((double)r / 255) - 0.5) * k - 0.5) * 255);
			if(r < 0) r = 0;
			if(r > 255) r = 255;
			g = round(((((double)g / 255) - 0.5) * k - 0.5) * 255);
			if(g < 0) g = 0;
			if(g > 255) g = 255;
			b = round(((((double)b / 255) - 0.5) * k - 0.5) * 255);
			if(b < 0) b = 0;
			if(b > 255) b = 255;
			c.setRed(r);
			c.setGreen(g);
			c.setBlue(b);
			img->setPixel(j, i, c.rgb());
		}
}
